#include <cstdio>
#include "stratum.h"
#include "utils.h"


void CommonLock(pthread_mutex_t* mutex) {
    if (g_debuglog_list) {
        int i = 0;
        for ( ;i < 10; i++) {
            int res = pthread_mutex_trylock(mutex);
            if (!res) {
                break;
            }
            usleep(100*STRATUM_MS);
        }
        if (i == 10) {
            printf("failed mutex2 %x <<----------\n", mutex);
        }
    } else {
        pthread_mutex_lock(mutex);
    }
}


void CommonUnlock(pthread_mutex_t* mutex) {
    pthread_mutex_unlock(mutex);
}

CommonList::CommonList()
    : m_count(0)
    , m_first(nullptr)
    , m_last(nullptr) {
    StratumCreateMutex(&m_mutex);
}

CommonList::~CommonList() {

}

void CommonList::enter() {
    pthread_mutex_lock(&m_mutex);
}

void CommonList::leave(){
    pthread_mutex_unlock(&m_mutex);
}


PCLI CommonList::addTail(void* data) {
    enter();
    PCLI item = new CommonListItem;
    item->data = data;
    m_count++;

    item->prev = m_last;
    item->next = nullptr;

    if (!m_first) {
        m_first->next = item;
    }
    if (item->prev) {
        item->prev->next = item;
    }
    leave();

    return item;
}

void CommonList::del(PCLI item) {
    enter();
    if (m_first == item) {
        m_first = item->next;
    }
    if (m_last == item) {
        m_last = item->prev;
    }
    if (item->next) {
        item->next->prev = item->prev;
    }
    if (item->prev) {
        item->prev->next = item->next;
    }
    item->next = nullptr;
    item->prev = nullptr;

    m_count--;
    delete item;

    leave();
}

void CommonList::del(void* data) {
    PCLI item = find(data);
    if (item) {
        del(item);
    }
}

void CommonList::delAll(LISTFREEPARAM freeParam) {
    enter();
    for (PCLI li1 = m_first; li1;) {
        PCLI tmp = li1;
        li1 = li1->next;
        if (freeParam) {
            freeParam(tmp->data);
        }
        delete tmp;
    }
    m_count = 0;
    m_first = nullptr;
    m_last = nullptr;
    leave();
}


PCLI CommonList::find(void* data) {
    enter();
    for (PCLI item = m_first; item; item = item->next) {
        if (data == item->data) {
            leave();
            return item;
        }
    }
    leave();
    return nullptr;
}

void CommonList::swap(PCLI i1, PCLI i2) {
    if (i1->prev) {
        i1->prev->next = i2;
    }
    if (i2->next) {
        i2->next->prev = i1;
    }

    i1->next = i2->next;
    i2->prev = i1->prev;

    i1->prev = i2;
    i2->next = i1;

    if (!i2->prev) {
        m_first = i2;
    }
    if (!i1->next) {
        m_last = i1;
    }
}

